home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-11-08 | 11.7 KB | 371 lines | [TEXT/MPS ] |
- //========================================================================================
- //
- // File: FWNewHel.cpp
- // Release Version: $ 1.0d11 $
- //
- // Copyright: (c) 1993, 1995 by Apple Computer, Inc., all rights reserved.
- //
- //========================================================================================
-
- #include "FWFound.hpp"
-
- #ifndef FWNEWHEL_H
- #include "FWNewHel.h"
- #endif
-
- #ifndef FWEXCDEF_H
- #include "FWExcDef.h"
- #endif
-
- #ifndef FWPRIMEM_H
- #include "FWPriMem.h"
- #endif
-
- #ifdef FW_USE_NEW_HELPER
-
- #if FW_LIB_EXPORT_PRAGMAS
- #pragma lib_export on
- #endif
-
- #ifdef FW_BUILD_MAC
- #pragma segment BEL
- #endif
-
- //========================================================================================
- // CLASS FW_CPrivSubHelper
- //========================================================================================
-
- void FW_CPrivSubHelper::InitializeStorageArray(FW_SPrivExceptionGlobals& globals,
- FW_CPrivSubHelper*array, int size)
- {
- for (int i=0; i<size-1; i++)
- {
- array[i].fSiblings = array+i+1;
- #ifdef FW_DEBUG
- array[i].fSubObject = 0;
- array[i].fSubObjectSize = 0;
- array[i].fSubObjectVTable = 0;
- #endif
- }
- array[size-1].fSiblings = NULL;
- globals.gSubHelperFreeListHead = array;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivSubHelper::operator new
- //----------------------------------------------------------------------------------------
-
- void* FW_CPrivSubHelper::operator new(size_t size)
- {
- FW_UNUSED(size);
- FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
- FW_CPrivSubHelper* head = globals.gSubHelperFreeListHead;
- FW_PRIV_ASSERT(head != NULL);
- globals.gSubHelperFreeListHead = head->fSiblings;
- return (void*) head;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivSubHelper::operator delete
- //----------------------------------------------------------------------------------------
-
- void FW_CPrivSubHelper::operator delete(void* object)
- {
- FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
- FW_CPrivSubHelper* subHelper = (FW_CPrivSubHelper*) object;
- FW_CPrivSubHelper* head = globals.gSubHelperFreeListHead;
- subHelper->fSiblings = head;
- #ifdef FW_DEBUG
- subHelper->fSubObject = 0;
- subHelper->fSubObjectSize = 0;
- subHelper->fSubObjectVTable = 0;
- #endif
- globals.gSubHelperFreeListHead = subHelper;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivSubHelper::FW_CPrivSubHelper
- //----------------------------------------------------------------------------------------
-
- FW_CPrivSubHelper::FW_CPrivSubHelper(_FW_CAutoDestructObject *subObject,
- size_t subObjectSize,
- FW_CPrivSubHelper *nextSubHelper)
- {
- fSubObject = subObject;
- fSubObjectSize = subObjectSize;
- fSubObjectVTable = *(void**)subObject;
- fSiblings = nextSubHelper;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivSubHelper::~FW_CPrivSubHelper
- //----------------------------------------------------------------------------------------
-
- FW_CPrivSubHelper::~FW_CPrivSubHelper()
- {
- }
-
- //========================================================================================
- // CLASS FW_CPrivNewHelper
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivNewHelper::Initialize
- //----------------------------------------------------------------------------------------
-
- void FW_CPrivNewHelper::Initialize(FW_SPrivExceptionGlobals& globals)
- {
- globals.gNewHelperStackBottom = (FW_CPrivNewHelper **)
- ::FW_PrimitiveAllocateBlock(kNewHelperStackSize);
-
- globals.gNewHelperStackTop = globals.gNewHelperStackBottom;
-
- globals.gSubHelperStorageArray = (FW_CPrivSubHelper *)
- ::FW_PrimitiveAllocateBlock(kSubHelperArrayByteSize);
-
- FW_CPrivSubHelper::InitializeStorageArray(globals,
- globals.gSubHelperStorageArray,
- kSubHelperArraySize);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivNewHelper::Terminate
- //----------------------------------------------------------------------------------------
-
- void FW_CPrivNewHelper::Terminate()
- {
- FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
- ::FW_PrimitiveFreeBlock(globals.gSubHelperStorageArray);
- ::FW_PrimitiveFreeBlock(globals.gNewHelperStackBottom);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivNewHelper::FW_CPrivNewHelper
- //----------------------------------------------------------------------------------------
-
- FW_CPrivNewHelper::FW_CPrivNewHelper(__FW_OperatorNewHandler newHandler,
- __FW_OperatorDeleteHandler deleteHandler) :
- fWatchedObject(0),
- fObjectVTable(0),
- fWatchedSize(0),
- fSubHelperList(0),
- fNewHandler(newHandler),
- fDeleteHandler(deleteHandler)
- {
- PushNewHelper();
- FW_END_CONSTRUCTOR
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivNewHelper::~FW_CPrivNewHelper
- //----------------------------------------------------------------------------------------
-
- FW_CPrivNewHelper::~FW_CPrivNewHelper()
- {
- FW_START_DESTRUCTOR
- if (fWatchedObject != 0)
- {
- DeleteWatchedObject();
- FW_CPrivNewHelper *temp = FW_CPrivNewHelper::PopNewHelper();
- FW_PRIV_ASSERT(temp == this);
- }
- else
- {
- FW_PRIV_ASSERT(fSubHelperList == 0);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivNewHelper::DeleteWatchedObject
- //----------------------------------------------------------------------------------------
-
- void FW_CPrivNewHelper::DeleteWatchedObject()
- {
- FW_CPrivSubHelper *next = fSubHelperList;
- while (next != NULL)
- {
- _FW_CAutoDestructObject *subObject = next->fSubObject;
- *(void**)subObject = next->fSubObjectVTable;
- subObject->__Delete();
-
- // Save next->fSiblings before deleting next! (see operator delete)
- FW_CPrivSubHelper *temp = next;
- next = next->fSiblings;
- delete temp;
- }
- if (fObjectVTable != 0)
- {
- *(void**)fWatchedObject = fObjectVTable;
- fWatchedObject->__Delete();
- }
- _FW_CAutoDestructObject::operator delete((void*) fWatchedObject);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivNewHelper::WatchObject
- //
- // This method is not really const,
- // but it reduces unnecessary warnings to declare it so.
- //----------------------------------------------------------------------------------------
-
- _FW_CAutoDestructObject * FW_CPrivNewHelper::WatchObject(
- _FW_CAutoDestructObject *watchedObject,
- size_t watchedSize) const
- {
- FW_CPrivNewHelper *self = (FW_CPrivNewHelper *) this;
- _FW_CAutoDestructObject *previous = fWatchedObject;
- self->fWatchedObject = watchedObject;
- self->fWatchedSize = watchedSize;
- return previous;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivNewHelper::ForgetObject
- //
- // This method is not really const,
- // but it reduces unnecessary warnings to declare it so.
- //----------------------------------------------------------------------------------------
-
- _FW_CAutoDestructObject * FW_CPrivNewHelper::ForgetObject() const
- {
- FW_CPrivNewHelper *self = (FW_CPrivNewHelper *) this;
- _FW_CAutoDestructObject *previous = fWatchedObject;
- self->fWatchedObject = 0;
- FW_PRIV_ASSERT(fSubHelperList == 0);
- return previous;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivNewHelper::PopNewHelper
- //----------------------------------------------------------------------------------------
-
- FW_CPrivNewHelper* FW_CPrivNewHelper::PopNewHelper()
- {
- FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
- FW_CPrivNewHelper** top = globals.gNewHelperStackTop;
- #ifdef FW_DEBUG
- FW_CPrivNewHelper** bottom = globals.gNewHelperStackBottom;
- FW_PRIV_ASSERT(top > bottom);
- #endif
- FW_CPrivNewHelper* helper = *--top;
- globals.gNewHelperStackTop = top;
- return helper;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivNewHelper::TopNewHelper
- //----------------------------------------------------------------------------------------
-
- FW_CPrivNewHelper* FW_CPrivNewHelper::TopNewHelper()
- {
- FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
- FW_CPrivNewHelper** top = globals.gNewHelperStackTop;
- FW_CPrivNewHelper** bottom = globals.gNewHelperStackBottom;
- FW_CPrivNewHelper* helper = 0;
- if (top > bottom)
- helper = top[-1];
- return helper;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivNewHelper::PushNewHelper
- //----------------------------------------------------------------------------------------
-
- void FW_CPrivNewHelper::PushNewHelper()
- {
- FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
- FW_CPrivNewHelper** top = globals.gNewHelperStackTop;
- #ifdef FW_DEBUG
- FW_CPrivNewHelper** bottom = globals.gNewHelperStackBottom;
- FW_PRIV_ASSERT(top < bottom + kMaxNewHelperStackItems);
- #endif
- *top++ = this;
- globals.gNewHelperStackTop = top;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivSubHelper::InList
- //----------------------------------------------------------------------------------------
-
- FW_CPrivSubHelper* FW_CPrivNewHelper::InList(_FW_CAutoDestructObject *subObject)
- {
- FW_CPrivSubHelper *next = fSubHelperList;
- while (next != NULL)
- {
- if (next->fSubObject == subObject)
- break;
- next = next->fSiblings;
- }
- return next;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivNewHelper::UpdateForEndConstructor
- //----------------------------------------------------------------------------------------
-
- void FW_CPrivNewHelper::UpdateForEndConstructor(_FW_CAutoDestructObject *object, size_t size)
- {
- if (object == fWatchedObject)
- {
- // Object is the object that was FW_NEWed.
- // Update the helper's copy of the vtbl pointer.
- fObjectVTable = *(void**)fWatchedObject;
- FW_PRIV_ASSERT(fObjectVTable != 0);
- }
- else
- {
- // Object must be a subobject of the object that was FW_NEWed.
- FW_PRIV_ASSERT(IsSubObject(object, fWatchedObject, fWatchedSize));
-
- // Is this subobject already attached, partially constructed?
- FW_CPrivSubHelper* subHelper = InList(object);
- if (subHelper==NULL)
- {
- // No, create a new helper to track this subobject
- fSubHelperList = new FW_CPrivSubHelper(object, size, fSubHelperList);
- }
- else
- {
- // Yes, update its vtable
- subHelper->fSubObjectVTable = *(void**)object;
- FW_PRIV_ASSERT(subHelper->fSubObjectVTable != 0);
- }
- }
-
- // Now, release any nested subobjects of this object
- // First, remove from head of list, updating fSubHelperList
- while (fSubHelperList != NULL && IsSubObject(fSubHelperList->fSubObject, object, size))
- {
- // Save fSubHelperList->fSiblings before deleting fSubHelperList!
- FW_CPrivSubHelper *temp = fSubHelperList;
- fSubHelperList = fSubHelperList->fSiblings;
- delete temp;
- }
-
- // Second, remove from internal to list, with fSubHelperList frozen
- if (fSubHelperList != NULL)
- {
- FW_PRIV_ASSERT(!IsSubObject(fSubHelperList->fSubObject, object, size));
- FW_CPrivSubHelper* prev = fSubHelperList;
- FW_CPrivSubHelper* next = prev->fSiblings;
- while (next!=NULL)
- {
- if (IsSubObject(next->fSubObject, object, size))
- {
- // unlink & delete next.
- prev->fSiblings = next->fSiblings;
- delete next;
- next = prev->fSiblings;
- }
- else
- {
- // advance prev to next
- prev = next;
- next = prev->fSiblings;
- }
- }
- }
- }
-
- #endif // FW_USE_NEW_HELPER
-